package com.wujunshen.utils;

import com.wujunshen.enumation.RequestMethod;
import com.wujunshen.exception.MyException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpHead;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;

/**
 * @author wujunshen
 * @date 2016/10/21
 */
@Slf4j
public final class NetUtils {
    private static final String DEFAULT_CHARSET = "UTF-8";
    private static final CloseableHttpClient HTTP_CLIENT = HttpClients.createDefault();

    /**
     * 返回  "&key=value&key=value..."
     * @param params 请求参数
     * @return 组合后的key，value结构
     */
    private static String assemble(Map<String, String> params) {
        StringBuilder sb = new StringBuilder();

        if ((params == null) || params.isEmpty()) {
            return sb.toString();
        }

        for (Map.Entry<String, String> entry : params.entrySet()) {
            sb.append("&").append(entry.getKey()).append("=").append(entry.getValue());
        }

        return sb.toString();
    }

    /**
     * 创建http连接
     * @param url    http请求url
     * @param params 请求参数
     * @return 封装好的请求体
     */
    private static HttpRequestBase buildHttpRequest(
            String url, Map<String, String> params, RequestMethod requestMethod) {
        String assembleParams = assemble(params);

        switch (requestMethod) {
            case GET:
                return new HttpGet(url + "?" + assembleParams);

            case POST:
                HttpPost httpPost = new HttpPost(url);

                httpPost.setEntity(buildParams(params));

                return httpPost;

            case HEAD:
                return new HttpHead(url + "?" + assembleParams);

            default:
                throw new MyException("no support request method [" + requestMethod.name() + "] now.");
        }
    }

    private static HttpEntity buildParams(Map<String, String> params) {
        List<NameValuePair> formParams = new ArrayList<>();

        params.forEach((key, value) -> formParams.add(new BasicNameValuePair(key, value)));

        try {
            return new UrlEncodedFormEntity(formParams, DEFAULT_CHARSET);
        } catch (UnsupportedEncodingException e) {
            throw new MyException("build params exception, params[" + params + "]", e);
        }
    }

    /**
     * 发送Http请求
     * @param url           url
     * @param params        请求参数
     * @param headers       请求头
     * @param requestMethod 请求方法
     * @return http响应
     */
    static CloseableHttpResponse sendHttpRequest(
            String url, Map<String, String> params, Map<String, String> headers, RequestMethod requestMethod) {
        try {
            HttpRequestBase httpRequest = buildHttpRequest(url, params, requestMethod);

            setHeaders(httpRequest, headers);

            return HTTP_CLIENT.execute(httpRequest);
        } catch (IOException e) {
            log.info("send request fail url[{}]", url);

            return null;
        }
    }

    private static void setHeaders(HttpRequestBase httpRequest, Map<String, String> headers) {
        if ((headers != null) && !headers.isEmpty()) {
            headers.forEach(httpRequest::setHeader);
        }
    }
}
